

from Queue import Queue
#device_list, scenario_match,scenario_list

from init import init
from Command import Command

device_list,\
scenario_match,\
scenario_list,\
statue_list = init()
command_list=scenario_match.keys()

def is_hex_num(string):
    '''Check if a string is in hex'''
    if type(string)!=(type('1')):raise TypeError
    h='0123456789ABCDEF'
    for char in string:
        if not char in h:return False
    return True

#command_queue stores all the commands which are ready to send'
command_queue=Queue()

def command_of_scenario(scenario_name,parameter):
    '''This function will return (in a list) all the code of action
    in a parameter-given scenario.'''
    action_list_filled =[] #This is the result list to return.

    parameter_dict={}
    for p in parameter:
        if '=' in p:
            ll=p.split('=')
            parameter_dict[ll[0]]=ll[1]

    action_list=scenario_list[scenario_name]['Action']
    # print action_list
    # print parameter,'\n'

#   Now, for every command in the scenario, we calculate its real code.
    for action_str in action_list:
        action=action_str.split(',')
        if type(action)!=type([1]): raise RuntimeError("Type of code is not list")

        device_name=action[0][0:3]
        action_cfg=device_list[device_name]['Function'][action[0]]
        # print 'action:', action
        # print 'action_cfg:',action_cfg

        # Now format the action.
        action[0]=action_cfg[0]
        for i in range(1,len(action)):
            if is_hex_num(action[i])==False: #this action[i] is a parameter like ['address']
                #replace the field with code
                if (parameter_dict.get(action[i],None)!=None):
                    action[i]=parameter_dict[action[i]]
                else:  raise RuntimeError(action[i]+':Parameter not found')
            action[i]=action_cfg[i]+'='+action[i]
        # print 'after_action:',action
#       Here 'action' is like ['AF[..]0[.]02DF', 'address=0A', 'circuit=1']

        c=Command(action_cfg[0],action_cfg[1:])
        final_command_code=c.fill(action[1:])
        # print final_command_code
#       This is the final result (of one command)
        action_list_filled.append(final_command_code)
    return action_list_filled                     

def command_match(std_command,command):
    '''Internal function of cut_command, used to check if the command from buffer and the command in the config can match.'''
    for index in range(len(command)):
        if not(command[index]=='.' or command[index]==std_command[index]) :
            return False
    return True
         
def cut_command(buffer_str,command_list):
    '''This function gets the commands in the buffer.
    It will add the actions to the queue and return the remaining buffer.'''
    
    can_match=False
    #if no command can be match(which means something wrong), clear the buffer

    for command in command_list:
        #first we try to find the real command to match
        now_command=command
        command=command.replace('[','').replace(']','')
        command_len=len(command)
        if len(buffer_str)<command_len: continue #Impossible to match

        if command_match(buffer_str[:command_len],command): #match successfully
            can_match=True

            now_scenario=scenario_match[now_command]
            code=buffer_str[:command_len]
            buffer_str=buffer_str[command_len:]

##          Read the parameter
            c=Command(now_command,now_scenario[1:])
            parameter=c.extract(code)
            # print now_scenario[0]
            # print parameter
##          Parameter got.

##          Now use the scenario and parameter to get all command, and put the command to the queue.
            # print scenario_list[now_scenario[0]]
            now_scenario_name=now_scenario[0]
            cmd_list=command_of_scenario(now_scenario_name,parameter)
            for cmd in cmd_list:
                command_queue.put(cmd) 

    if not can_match:
        print 'Buffer string %s can not be matched. Now clear the buffer.' % buffer_str
        buffer_str=''       
    return buffer_str

def one_step(buffer_str):
    buffer_str=cut_command(buffer_str,command_list)

    while not command_queue.empty():
        print command_queue.get()
        # Here we should send these command
    return buffer_str

def main():
    buffer_str='55001A080100123'
    for i in range(3):
        print 'Time %s' % (i+1) 
        buffer_str=one_step(buffer_str)
        # print buffer_str 


if __name__ == '__main__':
    main()

            
